package application

import (
	"context"
	"github.com/edgexfoundry/edgex-go/internal/app/core/metadata/container"
	"github.com/edgexfoundry/edgex-go/internal/app/dtos"
	"github.com/edgexfoundry/edgex-go/internal/app/models"
	"github.com/edgexfoundry/edgex-go/internal/pkg/correlation"
	bootstrapContainer "github.com/edgexfoundry/go-mod-bootstrap/v2/bootstrap/container"
	"github.com/edgexfoundry/go-mod-bootstrap/v2/di"
	"github.com/edgexfoundry/go-mod-core-contracts/v2/errors"
)

func AddProduct(p models.Product, ctx context.Context, dic *di.Container) (id string, edgeXerr errors.EdgeX) {
	dbClient := container.DBClientFrom(dic.Get)
	lc := bootstrapContainer.LoggingClientFrom(dic.Get)

	//validateProductCallback(ctx, dic, dtos.FromProductModelToDto(p))
	addedProduct, err := dbClient.AddProduct(p)
	if err != nil {
		return "", errors.NewCommonEdgeXWrapper(err)
	}

	lc.Debugf(
		"Product created on DB successfully. Product ID: %s, Correlation-ID: %s ",
		addedProduct.Id,
		correlation.FromContext(ctx),
	)

	//device := dtos.FromDeviceModelToDTO(d)
	//go addDeviceCallback(ctx, dic, device)
	//
	//go publishDeviceSystemEvent(common.DeviceSystemEventActionAdd, d.ServiceName, d, ctx, lc, dic)

	return addedProduct.Id, nil
}

func AllProducts(offset int, limit int, groupId string, dic *di.Container) (products []dtos.Product, totalCount uint32, err errors.EdgeX) {
	dbClient := container.DBClientFrom(dic.Get)
	productModels, err := dbClient.AllProducts(offset, limit, groupId)
	if err == nil {
		totalCount, err = dbClient.AllProductCount(groupId)
	}
	if err != nil {
		return products, totalCount, errors.NewCommonEdgeXWrapper(err)
	}
	products = make([]dtos.Product, len(productModels))
	for i, p := range productModels {
		products[i] = dtos.FromProductModelToDto(p)
	}
	return products, totalCount, nil
}

/**
 * @Description 产品查询-查询所有
 * @method
 * @auth kely
 * @Date ${DATE}
 * @Param
 * @return
 **/

func OwnProducts(dic *di.Container) (products []dtos.Product, totalCount uint32, err errors.EdgeX) {
	dbClient := container.DBClientFrom(dic.Get)
	productModels, err := dbClient.OwnProducts()
	if err == nil {
		totalCount = uint32(len(productModels))
	}
	if err != nil {
		return products, totalCount, errors.NewCommonEdgeXWrapper(err)
	}
	products = make([]dtos.Product, len(productModels))
	for i, p := range productModels {
		products[i] = dtos.FromProductModelToDto(p)
	}
	return products, totalCount, nil
}

// ProductByName 通过产品名称进行查询
//func ProductByName(name string, dic *di.Container) (product dtos.Product, err errors.EdgeX) {
//	// 检查产品名称是否存在
//	if name == "" {
//		return product, errors.NewCommonEdgeX(errors.KindContractInvalid, "name is empty", nil)
//	}
//	dbClient := container.DBClientFrom(dic.Get)
//	p, err := dbClient.ProductByName(name)
//	if err != nil {
//		return product, errors.NewCommonEdgeXWrapper(err)
//	}
//	product = dtos.FromProductModelToDto(p)
//	return product, nil
//}

func ProductById(id string, dic *di.Container) (product dtos.Product, err errors.EdgeX) {
	if id == "" {
		return product, errors.NewCommonEdgeX(errors.KindContractInvalid, "id is empty", nil)
	}
	dbClient := container.DBClientFrom(dic.Get)
	p, err := dbClient.ProductById(id)
	if err != nil {
		return product, errors.NewCommonEdgeXWrapper(err)
	}
	product = dtos.FromProductModelToDto(p)
	return product, nil
}

func ProductDelete(productId string, dic *di.Container) errors.EdgeX {
	dbClient := container.DBClientFrom(dic.Get)

	exists, err := dbClient.ProductIdExists(productId)
	if err != nil {
		return errors.NewCommonEdgeXWrapper(err)
	} else if !exists {
		return errors.NewCommonEdgeX(errors.KindInvalidId, "产品不存在", nil)
	}

	err = dbClient.ProductDelete(productId)
	if err != nil {
		return errors.NewCommonEdgeXWrapper(err)
	}
	return nil
}

func ProductUpdate(product models.Product, ctx context.Context, dic *di.Container) errors.EdgeX {
	dbClient := container.DBClientFrom(dic.Get)
	lc := bootstrapContainer.LoggingClientFrom(dic.Get)

	exists, err := dbClient.ProductIdExists(product.Id)
	if err != nil {
		return errors.NewCommonEdgeXWrapper(err)
	} else if !exists {
		return errors.NewCommonEdgeX(errors.KindInvalidId, "产品不存在", nil)
	}

	err = dbClient.ProductUpdate(product)
	if err != nil {
		return errors.NewCommonEdgeXWrapper(err)
	}
	lc.Debugf("Product Updated on DB successfully.")
	return nil
}

func ProductProfileByProductId(productId string, dic *di.Container) (productProfile dtos.ProductProfile, err errors.EdgeX) {
	dbClient := container.DBClientFrom(dic.Get)
	// 查询该产品的ProductCommand数量
	totalCount, err := dbClient.AllFunctionCountByProductId(productId)
	if err != nil {
		return productProfile, errors.NewCommonEdgeXWrapper(err)
	}
	// 查询该产品的ProductCommand
	productFunctions, err := dbClient.AllFunctionsByProductId(0, int(totalCount), productId)
	if err != nil {
		return productProfile, errors.NewCommonEdgeXWrapper(err)
	}
	productProfile.ProductCommands = make([]dtos.ProductCommand, len(productFunctions))
	for i := range productFunctions {
		productProfile.ProductCommands[i] = dtos.FromProductFunctionCommandModelToDto(productFunctions[i].Command)
	}
	// 查询该产品的ProductResource数量
	totalCount, err = dbClient.AttributeCountByProductId(productId)
	if err != nil {
		return productProfile, errors.NewCommonEdgeXWrapper(err)
	}
	// 查询该产品的ProductResource
	productAttributes, err := dbClient.AttributesByProductId(0, int(totalCount), productId)
	if err != nil {
		return productProfile, errors.NewCommonEdgeXWrapper(err)
	}
	productProfile.ProductResources = make([]dtos.ProductResource, len(productAttributes))
	for i := range productAttributes {
		productProfile.ProductResources[i] = dtos.FromProductResourceModelToDto(productAttributes[i].Resource)
	}
	return productProfile, nil
}

func ProductsByName(offset int, limit int, name string, groupId string, dic *di.Container) (products []dtos.Product, totalCount uint32, err errors.EdgeX) {
	dbClient := container.DBClientFrom(dic.Get)
	productsByName, totalCount, err := dbClient.ProductsByName(offset, limit, name, groupId)
	if err != nil {
		return products, totalCount, errors.NewCommonEdgeXWrapper(err)
	}
	products = make([]dtos.Product, 0)
	for _, v := range productsByName {
		products = append(products, dtos.FromProductModelToDto(v))
	}
	return products, totalCount, nil
}

//func ProductsByGroupId(groupId string, offset int, limit int, dic *di.Container) (products []dtos.Product, totalCount uint32, err errors.EdgeX) {
//	dbClient := container.DBClientFrom(dic.Get)
//	productModels, err := dbClient.ProductsByGroupId(groupId, offset, limit)
//	if err == nil {
//		totalCount, err = dbClient.ProductCountByGroupId(groupId)
//	}
//	if err != nil {
//		return products, totalCount, errors.NewCommonEdgeXWrapper(err)
//	}
//	products = make([]dtos.Product, len(productModels))
//	for i, p := range productModels {
//		products[i] = dtos.FromProductModelToDto(p)
//	}
//	return products, totalCount, nil
//}

//func AllProductsWithDeviceNum(offset int, limit int, dic *di.Container) (products []dtos.Product, totalCount uint32, err errors.EdgeX) {
//	dbClient := container.DBClientFrom(dic.Get)
//	productModels, err := dbClient.AllProductsWithDeviceNum(offset, limit)
//	if err == nil {
//		totalCount, err = dbClient.AllProductCount()
//	}
//	if err != nil {
//		return products, totalCount, errors.NewCommonEdgeXWrapper(err)
//	}
//	products = make([]dtos.Product, len(productModels))
//	for i, p := range productModels {
//		products[i] = dtos.FromProductModelToDto(p)
//	}
//	return products, totalCount, nil
//}
